#pragma
#include <iostream>
#include <string>
#include <unordered_set>
#include <cstdio>
#include "Log.hpp"

#define BUFFER_SIZE 1024
const char *sep = " ";

class CommandExcute
{
private:
    bool CheckSafe(const std::string &command)
    {
        // 获取指令前缀
        auto pos = command.find(sep);
        std::string PrefixCommand = command.substr(0, pos);

        auto iter = _legalInstruction.find(PrefixCommand);
        if (iter == _legalInstruction.end())
            return false;
        return true;
    }

    void LoadConf(const std::string &confPath)
    {
        // 读取文件
        std::ifstream in(confPath);
        if (!in.is_open())
        {
            LOG(FATAL, "open %s error\n", confPath.c_str());
            return;
        }

        std::string line;
        while (std::getline(in, line))
        {
            LOG(DEBUG, "load command [%s] success\n", line.c_str());
            _legalInstruction.insert(line);
        }
        in.close();
    }

public:
    CommandExcute(const std::string &confPath)
        : _confPath(confPath)
    {
        // 加载合法指令
        LoadConf(_confPath);
    }

    std::string Excute(const std::string &command)
    {
        // 在系统部分我们使用 1. fork && pipe  2. exec  3. dup
        // 这里我们使用popen函数做这些工作

        // 在执行之前可以判断指令的安全性，以防止用户使用一些危险的指令

        std::string result;
        if (CheckSafe(command))
        {
            // 我们需要读取popen执行命令后的结果
            FILE *fp = popen(command.c_str(), "r");
            if (NULL == fp)
            {
                LOG(DEBUG, "popen error");
            }
            char buffer[BUFFER_SIZE];
            while (NULL != fgets(buffer, BUFFER_SIZE, fp))
            {
                result += buffer;
            }

            return result;
            pclose(fp);
        }

        // 非法指令
        return "非法指令";
    }

    ~CommandExcute()
    {
    }

private:
    std::string _confPath;
    std::unordered_set<std::string> _legalInstruction;
};